home *** CD-ROM | disk | FTP | other *** search
- From: Dennis Bednar <talcott!seismo!rlgvax!dennis>
- Subject: hdiff: - source file compare program
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 117
- Submitted by: Dennis Bednar <talcott!seismo!rlgvax!dennis>
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # hdiff.hlp
- # Makefile
- # hdiff.c
- # remwhite.c
- # stripnl.c
- # stripnl.h
- # This archive created: Sat Feb 8 07:42:17 1986
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'hdiff.hlp'" '(2433 characters)'
- if test -f 'hdiff.hlp'
- then
- echo shar: will not over-write existing file "'hdiff.hlp'"
- else
- cat << \SHAR_EOF > 'hdiff.hlp'
- hdiff [-cdmvw] oldfile newfile
-
- Source file compare program.
- Yet another source compare program like diff. This one reports moved lines,
- not delete/insert as the UNIX diff does. The h is in honor of Paul Heckel,
- the guy who first wrote about this algorithm in CACM July 1978.
-
- One of c,d, or m should be used to adjust the internal algorithm.
- Currently I am playing with the algorithm.
-
- Switches
- -c = use a "count between the start of the other move block and
- the first line in the other file which matched this move
- block" to determine moved blocks [DEFAULT]
- -d = use a "drop" or relative slope to determine moved blocks
- -m = use "mononotonically increasing by one" to determine moved blocks
- -v = verbose (debugging)
- -w = compress white space only on each line before comparison,
- and remove leading white space (remwhite -a option).
-
- (see CACM, April 78, "A Technique for Isolating Differences Between Files",
- by Paul Heckel).
-
- Output:
- The output is identical in meaning to the output from UNIX diff,
- except that a "move" command is present here, but not in diff.
-
- DELETES
- -------
- old d new // Single line delete - Old line number 'old' is
- // deleted after new line numbered 'new'
- startold,endold d new // Block line delete - Old block of lines 'startold'
- // to 'endold' are deleted after new line number 'new'
-
- INSERTS
- -------
- old a new // After old line number 'old' is new line number 'new'
- old a startnew,endnew // After old line number 'old', new lines numbered
- // 'startnew' to 'endnew'
-
- CHANGES
- -------
- old c new // Change one line to one new line. The old line
- // numbered 'old' becomes new line numbered 'new'
- old c startnew,endnew // Change one line to a block of lines. Old line
- // numbered 'old' becomes the new set of lines.
- startold,endold c new // Change a block of old lines to one new line.
- startold,endold c startnew,endnew // Change a block of lines to
- // a different block of lines.
-
- MOVES
- -----
- old m new // Old line number 'old' is moved to new line
- // number 'new'
- startold,endold m startnew,endnew // The old block of lines have been moved
- // and the old line numbers have changed.
-
-
- For DELETES, INSERTS, and CHANGES (but not MOVES) the old line and new lines
- are displayed as follows (same as the UNIX diff):
- < old line
- > new line
-
- BUGS:
- Hdiff is limited to files with at most 5000 lines per file.
- To fix, recompile hdiff.c with a larger MAXLINES #define.
- SHAR_EOF
- if test 2433 -ne "`wc -c < 'hdiff.hlp'`"
- then
- echo shar: error transmitting "'hdiff.hlp'" '(should have been 2433 characters)'
- fi
- fi
- echo shar: extracting "'Makefile'" '(1034 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- SRC = hdiff.c remwhite.c stripnl.c stripnl.h hdiff.mk
- # also the hdiff help file is source but it is renamed on the copy
-
- # change this for your site
- INSTALLDIR = .
-
-
- hdiff: hdiff.o remwhite.o stripnl.o
- cc -O hdiff.o remwhite.o stripnl.o
- mv a.out hdiff
-
- hdiff.o: stripnl.h
- cc -O -c hdiff.c
-
- remwhite.o: stripnl.h
- cc -O -USTAND -c remwhite.c
-
- stripnl.o: stripnl.h
- cc -O -c stripnl.c
-
- clean:
- rm -f hdiff.o remwhite.o stripnl.o hdiff
-
- install: hdiff
- cp hdiff $(INSTALLDIR)
-
- # distribute hdiff. personal for dennis only.
- dist:
- rm -rf /tmp/dpb
- mkdir /tmp/dpb
- cp $(SRC) /tmp/dpb
- cp ../help/hdiff /tmp/dpb/hdiff.hlp # help file
- (cd /tmp/dpb; make -f hdiff.mk makeshar)
-
- makeshar:
- splitfiles * # split source files into little bundles
- for i in list.* ; \
- do \
- makeshar `cat $$i` > shar.$$i ; \
- done
-
-
- # you must run make -f hdiff.mk makeshar first
- # sends shar files to mod.sources
- # hardcoded for 2 bundles
- sendtonet:
- for i in 1 2 ; \
- do \
- Mail < shar.list.$$i -s "hdiff: - part $$i of 2" sources@panda.uucp; \
- done
- SHAR_EOF
- if test 1034 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 1034 characters)'
- fi
- fi
- echo shar: extracting "'hdiff.c'" '(34748 characters)'
- if test -f 'hdiff.c'
- then
- echo shar: will not over-write existing file "'hdiff.c'"
- else
- cat << \SHAR_EOF > 'hdiff.c'
- /*
- * f=hdiff.c (In honor of Mr Heckel, the guy who thought up this
- * algorithm).
- *
- * author - dennis bednar 8 22 84
- * Source file comparison program similar to UNIX diff, except this
- * version outputs moved blocks whereas UNIX diff reports it as
- * delete/add blocks.
- *
- * Algorithm from "A Technique for Isolating Differences Between Files"
- * CACM, April 1978, by Paul Heckel.
- * Some ideas for pass 6 were borrowed from "What's The Diff? -- A File
- * Comparator for CP/M", Dr. Dobb's Journal, August 1984, by D.E. Cortesi.
- * The borrowed idea was that when you are at the beginning of two
- * blocks of lines which link with lines in the other file, but don't
- * match, then the smaller ascending block is the "moved block".
- *
- * The pass5a () is coded directly from his his pass5 Pascal procedure.
- * It doesn't work if the old line being looked up in the symbol table
- * isn't unique!!! You would have to change the format of the linerec
- * record to make it work. That's why it's commented out.
- *
- * Output
-
- DELETES
- -------
- old d new // Single line delete - Old line number 'old' is
- // deleted after new line numbered 'new'
- startold,endold d new // Block line delete - Old block of lines 'startold'
- // to 'endold' are deleted after new line number 'new'
-
- INSERTS
- -------
- old a new // After old line number 'old' is new line number 'new'
- old a startnew,endnew // After old line number 'old', new lines numbered
- // 'startnew' to 'endnew'
-
- CHANGES
- -------
- old c new // Change old line numbered 'old' to new line numbered
- // 'new'
- old c startnew,endnew // Change one line to a block of lines. Old line
- // numbered 'old' becomes the new set of lines.
- startold,endold c new // Change a block of old lines to one new line.
- startold,endold c startnew,endnew // Change a block of lines to
- // a different block of lines.
-
- MOVES
- -----
- old m new // Old line number 'old' is moved to new line
- // number 'new'
- startold,endold m startnew,endnew // The old block of lines have been moved
- // and the old line numbers have changed.
-
-
- For DELETES, INSERTS, and CHANGES (but not MOVES) the old line and new lines
- are displayed as follows:
- < old line
- > new line
-
- */
-
- #include <stdio.h>
- #include "stripnl.h"
-
- /* choose SKIPCOUNT and BIGPRIME as follows:
- * BIGPRIME > 2*MAXLINES in case both files have all unique lines
- * such that SKIPCOUNT*tablesize probes will hit every slot in hash tbl
- * (hint: use the hashtbl a.out to help you)
- */
- #define MAXLINES 5000 /* max lines per file that can handle */
- #define BIGPRIME 10001 /* ideally a prime number > 2*MAXLINES for hash into symtbl */
- #define _MAXLINE1 MAXLINES+2 /* two extra for first, last sentinel */
- #define LINESIZE 1024 /* max chars per line */
- #define _LINESIZE LINESIZE+2 /* two extra for '\n', '\0' fgets rtns */
- #define SKIPCOUNT 4 /* reprobe into hash symbol table */
- #define CHANGESEP "---\n" /* line separator for change block */
- #define ZAPFLAG 1 /* 1 = yes, remove leading white space */
-
-
-
-
- /* structure for old, new files. One structure per line.
- * An array oa for the old file, and an array na for the new file.
- * If the line 'oldi' in the old file has NOT been matched to a line in
- * the new file then oa[oldi].flag == L_SYMINDX.
- * Similarly if the line 'newi' in the new file has NOT been matched to
- * a line in the old file, then na[newi].flag == L_SYMINDX.
- * When line 'oldi' in the old file has been matched to line 'newi'
- * in the new file, then oa[oldi].flag == L_LINENUM,
- * na[newi].flag == L_LINENUM, and each line points to the other, e.g.,
- * oa[oldi].lineloc == newi, and na[newi].lineloc == oldi.
- */
- struct linerec {
- int lineloc; /* line number in other file or symtbl index */
- int flag; /* tells which as defined below */
- };
- #define L_LINENUM 0
- #define L_SYMINDX 1
-
-
-
- /* symbol table structure. One per unique line in both files. */
- /* the line is keyed into the array via a hash code */
- struct symrec {
- char *stashline; /* saved line in malloc'ed memory */
- int ocount; /* count of lines in old file, 0,1,many */
- int ncount; /* count of lines in new file, 0,1,many */
- int olinenum; /* line number in the old file */
- };
-
-
-
-
- /*globals */
- char *cmd, /* name of this command */
- errbuf [_LINESIZE], /* build err msg for perror */
- linebuf [_LINESIZE], /* read line from either file into here */
- runflag [26], /* array of options flags set */
- *oldfile, /* name of old file */
- *newfile; /* name of new file */
-
- FILE *oldfp, /* stream for old file */
- *newfp; /* stream for new file */
-
- struct linerec
- oa [_MAXLINE1], /* for old file */
- na [_MAXLINE1]; /* for new file */
-
- struct symrec
- symtbl [BIGPRIME]; /* symbol table of all lines seen */
-
- int lastnew, /* total lines read from new file */
- lastold, /* total lines in old file */
- numsymbols, /* number of entries in symbol table */
- debug; /* debug flag set by -d flag */
-
-
-
-
- /* external non-integer functions */
- FILE *fopen(); /* fopen (3) */
- char *malloc (); /* malloc (3) */
- char *remwhite (); /* remove white space from string */
-
- /* internal non-integer functions */
- unsigned int hashline ();
-
-
- main (argc, argv)
- int argc;
- char **argv;
-
- {
- int usage; /* TRUE iff there is a usage error */
-
- /* name of command */
- cmd = argv [0];
-
- /* check arguments and assign global file names */
- usage = 0; /* assume no usage error */
- debug = 0; /* assume no debugging wanted */
- if (argc == 3)
- {
- oldfile = argv [1];
- newfile = argv [2];
- }
- else if (argc == 4 && *argv[1] == '-')
- {
- register char *cp;
- for (cp = argv[1]+1; *cp; ++cp)
- if ('a' <= *cp && *cp <= 'z')
- switch (*cp) {
- case 'v': /* verbose - debug */
- case 'd': /* drop */
- case 'm': /* monotonical by 1 */
- case 'c': /* count */
- case 'w': /* white space */
- if (*cp == 'v')
- debug = 1;
- runflag [*cp - 'a'] = 1;
- break;
- default:
- usage = 1;
- break;
- }
- else
- usage = 1;
- oldfile = argv[2];
- newfile = argv[3];
- }
- else
- usage = 1;
-
- if (usage)
- {
- fprintf (stderr, "usage: %s [-cdmvw] oldfile newfile\n", cmd);
- exit (1);
- }
-
-
- /* open both files */
- openfiles ();
-
- initvars ();
-
- src_compare ();
-
- /* close both files */
- closefiles ();
-
- }
-
- initvars ()
- {
- numsymbols = 0;
- }
-
-
-
- /*
- * compare the 2 files in 6 easy passes
- */
-
- src_compare ()
- {
- pass1 (); /* read, store new file */
- pass2 (); /* read, store old file */
- pass3 (); /* match up lines which occur only once */
- pass4 (); /* apply rule 2 working toward end */
- pass5 (); /* apply rule 2 working toward beginning */
- /* pass5a (); /* convert block-moves to insert/deletes */
- /* dumparray (); /* see if internal tables are built correctly */
- pass6 (); /* print out differences */
- if (debug)
- printf ("debug: symbol table: occupied = %d, total = %d\n",
- numsymbols, BIGPRIME);
- }
-
- /*
- * pass 1
- * read in new file.
- */
-
- pass1 ()
- {
- int
- linenum, /* which line we are on */
- stat, /* result from stripnl */
- sindex; /* index into symbol table */
- char *cp; /* char pointer into line */
-
-
-
- /* read each line of new file in a loop. */
- /* stop if eof or can't handle that many lines */
- for (linenum = 0;
- fgets (linebuf, sizeof(linebuf), newfp) != (char *)NULL &&
- ++linenum <= MAXLINES; )
- {
-
- /* strip newline at end and make sure line wasn't too long */
- stat = stripnl (linebuf, sizeof(linebuf) );
-
- if (stat == L_SUCCESS)
- ;
- else if (stat == L_BADFORM)
- fprintf (stderr, "%s: Warning, line %d in file %s not terminated with newline\n",
- cmd, linenum, newfile);
- else
- {
- fprintf (stderr, "%s: line %d longer than %d chars in file %s\n",
- cmd, linenum, LINESIZE, newfile);
- exit (1);
- }
-
- /* if compressing white space, then compress into line buf */
- if (runflag ['w' - 'a'] )
- {
- char *cp;
- cp = remwhite (linebuf, ZAPFLAG);
- strcpy (linebuf, cp);
- }
-
- sindex = addsymbol (linebuf); /* put line into symbol tbl */
- if (symtbl [sindex].ncount < 2)
- ++symtbl [sindex].ncount;
- na [linenum].lineloc = sindex;
- na [linenum].flag = L_SYMINDX;
- }
-
- /* see if new file was empty */
- if (linenum == 0)
- {
- fprintf (stderr, "%s: New file %s is empty. Diff is delete entire old file.\n", newfile, cmd);
- exit (1);
- }
-
- if (linenum > MAXLINES)
- {
- fprintf (stderr, "%s: New file %s is too big. Last line read was %d.\n", cmd, newfile, MAXLINES);
- exit (1);
- }
-
- /* assign global number of new lines */
- lastnew = linenum;
- }
-
-
- /*
- * pass 2
- * read in old file.
- */
-
- pass2 ()
- {
- int
- linenum, /* which linenum we are on */
- stat, /* result from stripnl */
- sindex; /* index into symbol table */
- char *cp; /* char pointer into line */
-
-
-
- /* read each line of old file in a loop. */
- /* stop if eof or can't handle that many lines */
- for (linenum = 0;
- fgets (linebuf, sizeof(linebuf), oldfp) != (char *)NULL &&
- ++linenum <= MAXLINES; )
- {
-
- #if 0 /* old way */
- /* strip newline at end and make sure line wasn't too long */
- cp = &linebuf[strlen(linebuf)-1];
- if (*cp == '\n')
- *cp = '\0';
- else if (strlen(linebuf) < sizeof(linebuf)-1)
- fprintf (stderr, "%s: Warning, line %d in file %s not terminated with newline\n", cmd, linenum, oldfile);
- else
- {
- fprintf (stderr, "%s: line %d longer than %d chars in file %s\n",
- cmd, linenum, LINESIZE, oldfile);
- exit (1);
- }
- #endif
-
- /* strip newline at end and make sure line wasn't too long */
- stat = stripnl (linebuf, sizeof(linebuf) );
-
- if (stat == L_SUCCESS)
- ;
- else if (stat == L_BADFORM)
- fprintf (stderr, "%s: Warning, line %d in file %s not terminated with newline\n",
- cmd, linenum, oldfile);
- else
- {
- fprintf (stderr, "%s: line %d longer than %d chars in file %s\n",
- cmd, linenum, LINESIZE, oldfile);
- exit (1);
- }
-
-
- /* if compressing white space, then compress into line buf */
- if (runflag ['w' - 'a'] )
- {
- char *cp;
- cp = remwhite (linebuf, ZAPFLAG);
- strcpy (linebuf, cp);
- }
-
- sindex = addsymbol (linebuf); /* put line into symbol tbl */
- if (symtbl [sindex].ocount < 2)
- ++symtbl [sindex].ocount;
- symtbl[sindex].olinenum = linenum;
- oa [linenum].lineloc = sindex;
- oa [linenum].flag = L_SYMINDX;
- }
-
- /* see if old file was empty */
- if (linenum == 0)
- {
- fprintf (stderr, "%s: Old file %s is empty. Diff is add entire new file.\n", oldfile, cmd);
- exit (1);
- }
-
- if (linenum > MAXLINES)
- {
- fprintf (stderr, "%s: Old file %s is too big. Last line read was %d.\n", cmd, oldfile, MAXLINES);
- exit (1);
- }
-
- /* assign number of lines in old file */
- lastold = linenum;
- }
-
-
- /*
- * Add a line to the symbol table.
- * The hash function determines the initial probe into the symbol table.
- * If the line is new, then core is malloc'ed for storage, and
- * the 'value' is the pointer to the line (empty slot can be found).
- * If the line is old, the old index is returned.
- *
- * returns
- * index into symbol table
- * updated global 'numsymbols' for debugging.
- *
- */
- addsymbol (line)
- char *line;
- {
- int sindex, /* symbol table index */
- firstprobe; /* index of first probe into symbol tbl */
- char *cp; /* malloc char pointer */
-
- sindex = firstprobe = hashline (line, BIGPRIME);
-
- /* keep looping until empty slot found or table is full. */
- /* table cannot be full. */
- while (1)
- {
- /* if find an empty slot, add the line there. */
- if (symtbl [sindex].stashline == (char *)NULL)
- {
- cp = malloc (strlen (linebuf) + 1);
- if (cp == (char *)NULL)
- {
- fprintf (stderr, "%s: out of space in function addsymbol\n", cmd);
- exit (1);
- }
-
- /* copy the line to storage area */
- strcpy (cp, line);
-
- /* save the line in the symbol table entry */
- symtbl [sindex].stashline = cp;
-
- ++numsymbols;
-
- break;
- }
-
- /* if the line is already in the table, then done */
- else if (strcmp (symtbl [sindex].stashline, line) == 0)
- break;
-
- /* else it's a collision with a different line, so
- * let's do linear open addressing. That is, reprobe
- * SKIPCOUNT slots below, modulo the table size.
- * SKIPCOUNT == 1 means primaray clustering.
- * SKIPCOUNT > 1 means secondary clustering.
- * Check for overflow.
- */
- else
- {
- sindex += SKIPCOUNT;
- if (sindex >= BIGPRIME)
- sindex = 0; /* wraparound */
- if (sindex == firstprobe)
- {
- fprintf (stderr, "%s: symtbl overflow!\n", cmd);
- exit (1);
- }
- }
- }
-
-
- return sindex;
- }
-
-
- /*
- * pass 3.
- * Process NA array and link lines up which appear only once
- * in both files.
- * Link virtual line pointer at front and end of both files.
- */
-
- pass3 ()
- {
- int newi, /* loop counter thru na array */
- oldi, /* index into oa array */
- symi; /* index into symbol table array */
-
- /* loop thru all new lines. Those that occur once are linked to
- * each other instead of to the symbol table as they used to be.
- */
- for (newi = 1; newi <= lastnew; ++newi)
- {
- symi = na[newi].lineloc; /* get symbol tbl index */
- if ((symtbl[symi].ocount == 1) && (symtbl[symi].ncount == 1))
- {
- oldi = symtbl[symi].olinenum;
- linkup (oldi, newi);
- }
- }
-
- /* link the virtual line 'begin' of each file to each other */
- linkup (0, 0);
-
- /* line the virtual line 'end' of each file to each other */
- linkup (lastold+1, lastnew+1);
- }
-
-
- /*
- * pass 4
- * loop ascending thru new lines in na array.
- * If line newi in new file is linked to line oldi in old file,
- * but the next lines of each contain the same symbol table
- * pointer, then link na[newi+1] to oa[oldi+1].
- */
- pass4 ()
- {
- int newi,
- oldi;
-
- /* process 'begin', all lines in new file, but NOT virtual 'end' */
- for (newi = 0; newi <= lastnew; ++newi)
- {
- if (na[newi].flag == L_LINENUM)
- {
- oldi = na[newi].lineloc;
- if ((na[newi+1].flag == L_SYMINDX) &&
- (oa[oldi+1].flag == L_SYMINDX) &&
- (na[newi+1].lineloc == oa[oldi+1].lineloc))
- linkup (oldi+1, newi+1);
- }
- }
- }
-
-
- /*
- * pass 5
- * Process new file in descending order.
- * Similar to pass 4, but in reverse order.
- */
- pass5 ()
- {
- int newi,
- oldi;
-
- /* process 'end', all lines in new file, but NOT virtual 'begin' */
- for (newi = lastnew+1; newi > 0; --newi)
- {
- if (na[newi].flag == L_LINENUM)
- {
- oldi = na[newi].lineloc;
- if ((na[newi-1].flag == L_SYMINDX) &&
- (oa[oldi-1].flag == L_SYMINDX) &&
- (na[newi-1].lineloc == oa[oldi-1].lineloc))
- linkup (oldi-1, newi-1);
- }
- }
-
-
- }
-
-
- /*
- * pass 6
- * output the differences.
- */
- pass6 ()
- {
- int oldi, /* current line number in old file */
- newi, /* current line number in new file */
- oldmatch, /* true iff old line matches SOME line in new file */
- newmatch, /* true iff new line matches SOME line in old file */
- omatcount, /* match count in old file */
- nmatcount, /* match count in new file */
- odrop, /* old file "relative drop" of new line */
- ndrop, /* new file "relative drop" of old line */
- ocomp, /* comparison result for old file */
- ncomp, /* comparison result for new file */
- ospan, /* size of old monotonical block */
- nspan; /* size of new monotonical block */
-
- for (oldi = 0, newi = 0; oldi <= lastold+1 && newi <= lastnew+1;)
- {
-
- /* set flags to indicate if each line is linked
- * to another line in the other file.
- */
-
- /* is old line linked to another line in the new file? */
- oldmatch = (oa[oldi].flag == L_LINENUM);
-
- /* is new line linked to another line in the old file? */
- newmatch = (na[newi].flag == L_LINENUM);
-
-
- /* if old line moved from old file up (toward begin) in
- * new file, then we have already processed the block
- * move in the new file. Just skip the line in the old file.
- */
- if (oa[oldi].lineloc < newi && oldmatch)
- {
- ++oldi;
- continue;
- }
-
- /* if old line moved from old file down (toward end) in
- * old file, then we we have already processed the block
- * move in the old file. Just skip the line in the new file.
- */
- else if (na[newi].lineloc < oldi && newmatch)
- {
- ++newi;
- continue;
- }
-
-
- /* there are four combinations of booleans oldmatch and newmatch */
-
- /* if both lines are linked to SOME line in the other file */
- if (oldmatch && newmatch)
- {
- /* if both lines match each other, then go
- * to next line in both files
- */
- if (oa[oldi].lineloc == newi)
- {
- if (debug)
- printf ("debug: Same old line %d and new line %d\n", oldi, newi);
- ++oldi;
- ++newi;
- continue;
- }
-
- /* blocks not linked to each other.
- * If there are more lines in oldfile that
- * are monotonically increasing by one in
- * the new file, then this is normal, and the
- * new block is moved down in the old file.
- * If there are more lines in newfile that
- * are monotonically increasing by one in
- * the old file, then this is normal, and
- * the old block is moved down in the new file.
- */
-
- /* get size of old block which is monitonically
- * increasing by one in the new file.
- */
- ospan = oldmon (oldi);
-
- /* get size of new block which is monitonically
- * increasing by one in the old file.
- */
- nspan = newmon (newi);
-
- /* count the number of lines in the old file between
- * the current line and the line which corresponds
- * to the first new moved line.
- */
- omatcount = gomatch (oldi, na[newi].lineloc);
-
- /* count the number of lines in the new file between
- * the current line and the old moved line which
- * match.
- */
- nmatcount = gnmatch (newi, oa[oldi].lineloc);
-
- /* get number of old lines the new block drops down
- * into the old file. If old drop is < new drop
- * then the old block has moved down further into
- * the new file than the new block has moved down
- * into the old file. The relative steepness of the
- * slope of the line from oldi to its matched line
- * is more than the steepnes of the other slope,
- * and since line don't usually move far, assume
- * that the new to old move is a match, and the
- * old to new is an old block moved down.
- */
- odrop = na [newi].lineloc - oldi;
-
- /* same for new file */
- ndrop = oa [oldi].lineloc - newi;
-
- /* if 'd' flag is set, use 'drop' for match */
- if (runflag ['d' - 'a'])
- {
- ocomp = odrop;
- ncomp = ndrop;
- }
- /* if 'm' flag set, use bigger monotonically increasing
- * by 1 span
- */
- else if (runflag ['m' - 'a'])
- {
- ocomp = ospan;
- ncomp = nspan;
- }
- /* if 'c' flag then use match count */
- else if (runflag ['c' - 'a'])
- {
- ocomp = omatcount;
- ncomp = nmatcount;
- }
- /* default - best one */
- else
- {
- ocomp = omatcount;
- ncomp = nmatcount;
- }
-
-
-
- if (ocomp < ncomp) /* old block moved down */
- eatold (&oldi, ospan); /* eat old mv'ed blk */
- else /* new block moved down */
- eatnew (&newi, nspan); /* eat new mv'ed blk */
- }
-
- /* new lines added (inserted) into new file */
- else if (oldmatch && !newmatch)
- newinsert (oldi, &newi); /* skip new insert blk */
-
- /* old lines deleted from old file */
- else if (!oldmatch && newmatch)
- olddelete (&oldi, newi); /* skip old delete block */
-
- /* old lines changed into new file */
- else /* !oldmatch && !newmatch */
- oldchange (&oldi, &newi); /* skip old delete block and new insert block */
- }
- }
-
- /*
- * block of old lines beginning at linenum 'oldi' are matched with
- * a block of new lines. Count the number of lines in the old block
- * which are monotonically increasing by one in the new file.
- * returns -
- * size of old block
- */
- oldmon (oldi)
- int oldi;
- {
- int osize, /* size of old block */
- expnew, /* line number expected in new file */
- curoldnum; /* current line number in old file */
-
-
- curoldnum = oldi; /* save old line number so can tell
- * how big the old block is at the end
- */
-
- do
- {
- expnew = oa[curoldnum].lineloc + 1;
- ++curoldnum;
- }
- while ((curoldnum <= lastold+1) /* in bounds */
- && (expnew == oa[curoldnum].lineloc) /* monotonical by 1 */
- && (oa[curoldnum].flag == L_LINENUM)); /* match */
-
- osize = curoldnum - oldi;
-
- if (debug)
- printf ("debug: lines %d-%d of old file are monotonical\n", oldi, curoldnum-1);
-
- return osize;
- }
-
-
- newmon (newi)
- int newi;
- {
- int nsize, /* size of new block */
- expold, /* line number expected in old file */
- curnewnum; /* current line number in new file */
-
-
- curnewnum = newi; /* save new line number so can tell
- * how big the new block is at the end
- */
-
- do
- {
- expold = na[curnewnum].lineloc + 1;
- ++curnewnum;
- }
- while ((curnewnum <= lastnew+1) /* in bounds */
- && (expold == na[curnewnum].lineloc) /* monotonical by 1 */
- && (na[curnewnum].flag == L_LINENUM)); /* match */
-
- nsize = curnewnum - newi;
-
- if (debug)
- printf ("debug: lines %d-%d of new file are monotonical\n", newi, curnewnum-1);
-
- return nsize;
- }
-
-
- /*
- * eat old block beginning with old line number *'oldi' and 'ospan' lines
- * These old lines are moved down into the new file.
- * The output format is
- 5,6m7,8 // old lines 5-6 are moved to new lines 7-8
- 5m7 // old line 5 is moved to new line 7
- * returns
- * *oldi = updated old line number
- */
- eatold (oldi, ospan)
- int *oldi,
- ospan;
- {
- int newi;
-
- /* get starting line number of new block */
- newi = oa[*oldi].lineloc;
-
- /* how many lines in the old block - one or more? */
- if (ospan == 1)
- printf ("%dm%d\n", *oldi, newi);
- else if (ospan > 1)
- printf ("%d,%dm%d,%d\n", *oldi, *oldi+ospan-1, newi, newi+ospan-1);
- else
- {
- fprintf (stderr, "%s: unexpected negative ospan = %d in function eatold\n", ospan);
- exit (1);
- }
-
- /* return old line number after the old moved block */
- *oldi += ospan;
-
- }
-
-
- /*
- * eat the new block
- * Like eatold, but works on the new block.
- */
-
- eatnew (newi, nspan)
- int *newi,
- nspan;
- {
- int oldi;
-
- /* get starting line number in the old file */
- oldi = na[*newi].lineloc;
-
- if (nspan == 1)
- printf ("%dm%d\n", oldi, *newi);
- else if (nspan > 1)
- printf ("%d,%dm%d,%d\n", oldi, oldi+nspan-1, *newi, *newi+nspan-1);
- else
- {
- fprintf (stderr, "%s: unexpected negative nspan = %d in function eatnew\n", nspan);
- exit (1);
- }
-
- *newi += nspan;
- }
-
- /*
- * Print new lines inserted in old file to transform into new file
- * input
- * oldi - one after the current old line number !!!!!!!
- * *newi - first line number in new file of inserted line.
- * output
- * *newi - next line number in new file after inserted block.
- * printed lines of the form
- *
-
- 5a7 // after old line 5 add one newline as newline 7
- > new line 8
-
- * or
-
- 5a7,8 // after old line 5 add two newlines as newline 7 and 8
- > new line 7
- > new line 8
-
- */
- newinsert (oldi, newi)
- int oldi,
- *newi;
- {
- int nsize, /* number of lines inserted in new file */
- csize, /* current number of lines in a loop */
- curnewline; /* current line number in new file */
-
- if (debug)
- printf ("debug: Found New Insert. Old line %d. New line %d.\n", oldi, *newi);
-
- /* first compute size so we know which format to use (single line
- * insert or multiline insert)
- * Get the number of lines in the insert block.
- */
- nsize = inssize (*newi);
-
- if (nsize == 1)
- printf ("%da%d\n", oldi-1, *newi);
- else if (nsize > 1)
- printf ("%da%d,%d\n", oldi-1, *newi, *newi+nsize-1);
- else
- {
- fprintf (stderr, "%s: unexpected new block size = %d in function newinsert\n", nsize);
- exit (1);
- }
-
- /* print the new inserted lines */
- for (curnewline = *newi, csize = nsize; csize > 0; ++curnewline, --csize)
- printf ("> %s\n", symtbl [ na[curnewline].lineloc ].stashline);
-
- /* return the new line */
- *newi += nsize;
- }
-
-
-
-
- /*
- * Print that a group of lines in the old file was deleted
- * input -
- * *oldi - line number in old file where the group of lines begins
- * newi - line number + 1 in new file after which the delete occurs.
- * output
- * *oldi - updated with the next old line after the delete block
- 5d7 // old line 5 deleted after new line 7
- < old line 5
- 5,6d7 // old lines 5 and 6 deleted after new line 7
- < old line 5
- < old line 6
- *
- */
-
- olddelete (oldi, newi)
- int *oldi,
- newi;
- {
- int osize, /* number of lines deleted in old file */
- csize, /* current size in in the loop */
- curoldline; /* current line number in old file */
-
- if (debug)
- printf ("debug: Found Old Delete. Old line %d. New line %d.\n", *oldi, newi);
-
- /* first compute size so we know which format to use (single line
- * insert or multiline delete)
- * Get the number of lines in the old delete block.
- */
- osize = delsize (*oldi);
-
-
- /* print the header for the line deletes */
- if (osize == 1)
- printf ("%dd%d\n", *oldi, newi-1);
- else if (osize > 1)
- printf ("%d,%dd%d\n", *oldi, *oldi+osize-1, newi-1);
- else
- {
- fprintf (stderr, "%s: unexpected old block size = %d in function olddelete\n", osize);
- exit (1);
- }
-
- /* print the old deleted lines */
- for (curoldline = *oldi, csize = osize; csize > 0; ++curoldline, --csize)
- printf ("< %s\n", symtbl [ oa[curoldline].lineloc ].stashline);
-
- /* return the old line after the delete block */
- *oldi += osize;
- }
-
-
-
-
- /*
- * Print that a group of old lines has been updated to a group of new lines.
- * input
- * *oldi = line number of start of old lines
- * *newi = line number of start of new lines
- * output
- * *oldi = line number after block deleted in the old file
- * *newi = line number after block inserted in the new file
- * print statements according to one of 4 forms:
- startold c startnew
- startold c startnew,endnew
- startold,endold c startnew
- startold,endold c startnew,endnew
- * Examples
- 5c7 // old line 5 has been replace by new line 7
- < old line 5
- ---
- > new line 7
-
- 5,6c7,8 // old lines 5 and 6 have been replaced by new lines 7 and 8
- < old line 5
- < old line 6
- ---
- > new line 7
- > new line 8
- */
-
- oldchange (oldi, newi)
- int *oldi,
- *newi;
- {
- int curold, /* current line number in old file */
- curnew, /* current line number in new file */
- osize, /* size of block changed in old file */
- nsize, /* size of block changed in new file */
- csize, /* current block size for the loop */
- curoldline, /* current line number in old file */
- curnewline; /* current line number in new file */
-
- if (debug)
- printf ("debug: Found Changed Lines. Old line %d. New line %d\n", *oldi, *newi);
-
- /* get the size of the old deleted block and the new inserted block */
- osize = delsize (*oldi);
- nsize = inssize (*newi);
-
- /* print the header for the old deleted block */
- if (osize == 1)
- printf ("%dc", *oldi);
- else if (osize > 1)
- printf ("%d,%dc", *oldi, (*oldi)+osize-1);
- else
- {
- fprintf (stderr, "%s: unexpected old block size = %d in function oldchange\n", osize);
- exit (1);
- }
-
- /* print the header for the new inserted block */
- if (nsize == 1)
- printf ("%d\n", *newi);
- else if (nsize > 1)
- printf ("%d,%d\n", *newi, (*newi)+nsize-1);
- else
- {
- fprintf (stderr, "%s: unexpected new block size = %d in function oldchange\n", nsize);
- exit (1);
- }
-
- /* Now print the old changed (delete) lines */
- for (curoldline = *oldi, csize = osize; csize > 0; ++curoldline, --csize)
- printf ("< %s\n", symtbl [ oa[curoldline].lineloc ].stashline);
-
- /* print line change separator */
- printf (CHANGESEP);
-
- /* Now print the new changed (inserted) lines */
- for (curnewline = *newi, csize = nsize; csize > 0; ++curnewline, --csize)
- printf ("> %s\n", symtbl [ na[curnewline].lineloc ].stashline);
-
- /* return the new old and new lines */
- *oldi += osize;
- *newi += nsize;
- }
-
-
-
- /*
- * these next two routines are called upon by functions
- * olddelete, newinsert, and oldchange
- */
-
- /*
- * starting with line number 'newi' in the new file, count the number of
- * lines in the insert block.
- *
- * Loop thru the insert block. The block is a series of new lines
- * that aren't linked to lines in the old file. That is, each
- * inserted line points to a symbol table entry.
- */
- inssize (newi)
- int newi;
- {
- register
- int curnewline, /* current line number in new file */
- nsize; /* number of new lines in insert block */
-
-
- curnewline = newi;
- while (curnewline <= lastnew+1 && na[curnewline].flag == L_SYMINDX)
- ++curnewline;
-
- /* curnewline is now the new line number AFTER the insert block */
-
- /* compute the number of lines in the insert block */
- nsize = curnewline - newi;
-
- if (debug)
- printf ("debug: at new line %d, the insert block has %d lines\n", newi, nsize);
-
- return nsize;
- }
-
-
-
- /*
- * compute the number of lines in the old delete block beginning
- * with old line number 'oldi' and return it.
- *
- * Loop thru the delete block. The block is a series of old lines
- * that aren't linked to lines in the new file. That is, each
- * deleted line points to a symbol table entry.
- */
-
- delsize (oldi)
- int oldi;
- {
- register
- int curoldline, /* current line number in old file */
- osize; /* number of old lines in delete block */
-
- curoldline = oldi;
- while (curoldline <= lastold+1 && oa[curoldline].flag == L_SYMINDX)
- ++curoldline;
-
- /* curoldline is now the old line number AFTER the delete block */
-
- /* compute the number of lines in the delete block */
- osize = curoldline - oldi;
-
- if (debug)
- printf ("debug: at old line %d, the delete block has %d lines\n", oldi, osize);
-
- /* return the delete block size */
- return osize;
- }
-
-
-
-
-
-
- /*
- * dump the oa and na internal arrays which is the crudest way
- * to print the file comparisons.
- * This routine may be called in lieu of pass 6 as a debugging tool.
- */
- dumparray ()
- {
- int oldi,
- newi;
-
- for (oldi = 0; oldi <= lastold+1; ++oldi)
- if (oa[oldi].flag == L_LINENUM)
- printf ("oa[%d] = %d\n", oldi, oa[oldi].lineloc);
- else
- printf ("oa[%d] INSERTED.\n", oldi);
-
-
- for (newi = 0; newi <= lastnew+1; ++newi)
- if (na[newi].flag == L_LINENUM)
- printf ("na[%d] = %d\n", newi, na[newi].lineloc);
- else
- printf ("na[%d] DELETED.\n", newi);
- }
-
-
-
- /* borrowed from hashname.c
- * eventually will be removed.
- */
-
- unsigned int hashline (name,modval)
-
- register char *name;
- register unsigned int modval;
-
- {
- register unsigned int i;
-
- i=0;
- while (*name != '\0'){
- i=((i<<2)+(*name&~040))%modval;
-
- name++;
- }
-
- return(i);
- }
-
-
-
- /*
- * linkup line oldi in old file to line newi' in new file
- */
- linkup (oldi, newi)
- int oldi,
- newi;
- {
- oa[oldi].lineloc = newi;
- oa[oldi].flag = L_LINENUM;
- na[newi].lineloc = oldi;
- na[newi].flag = L_LINENUM;
- }
-
-
- /*
- * pass 5a converts block moves to delete/insert pairs
- */
- pass5a ()
- {
- int oldi,
- newi;
-
- for (oldi = 1, newi = 1; oldi <= lastold+1; )
- {
- while (oa[oldi].flag == L_SYMINDX && oldi <= lastold+1)
- ++oldi; /* skip deletes in old file */
- while (na[newi].flag == L_SYMINDX && newi <= lastnew+1)
- ++newi; /* skip inserts in new file */
- if (oldi > lastold+1)
- break;
- if (newi > lastnew+1)
- break;
-
- if (oa[oldi].lineloc == newi) /* begin matching lines */
- {
- oldi++;
- newi++;
- }
- else /* discontinuity ?*/
- {
- if (oa[oldi].lineloc != lastnew+1)
- resolve (oldi, newi); /* yes */
- else
- ; /* no, sentinel */
- }
- }
- }
-
-
- resolve (oldi, newi)
- int oldi,
- newi;
-
- {
- int xo, xn;
- int t, ospan, nspan;
- int symi;
-
- /* measure block starting at oa[oldi] */
- xo = oldi;
- do
- {
- t = 1 + oa[xo].lineloc;
- xo++;
- }
- while (t != oa[xo].lineloc);
- ospan = xo - oldi;
-
- /* measure block starting at na[newi] */
- xn = newi;
- do
- {
- t = 1 + na[xn].lineloc;
- xn++;
- }
- while (t != na[xn].lineloc);
- nspan = xn - newi;
-
-
-
- if (ospan < nspan)
- {
- xo = oldi;
- xn = oa[oldi].lineloc;
- t = ospan;
- oldi = oldi + ospan;
- }
- else
- {
- xn = newi;
- xo = na[newi].lineloc;
- t = nspan;
- newi = newi + nspan;
- }
-
- while (t > 0)
- {
- symi = 0;
- while (symi < BIGPRIME && symtbl[symi].olinenum != xo)
- symi++;
-
- if (symi >= BIGPRIME)
- {
- fprintf (stderr, "%s: can't find old line %d in symtbl\n", cmd, xo);
- dumpsym ();
- exit (1);
- }
-
-
- /* link the lines to the same symbol tbl entry */
- oa[xo].flag = L_SYMINDX;
- oa[xo].lineloc = symi;
- na[xn].flag = L_SYMINDX;
- na[xn].lineloc = symi;
-
- ++xo;
- ++xn;
- --t;
- }
- }
-
- /*
- * open global files 'oldfile' and 'newfile'
- */
- openfiles ()
- {
- /* open old source file for reading */
- oldfp = fopen (oldfile, "r");
- if (oldfp == (FILE *)NULL)
- {
- sprintf (errbuf, "%s: can't oldfile open %s", cmd, oldfile);
- perror (errbuf);
- exit (1);
- }
-
-
-
-
- /* open new source file for reading */
- newfp = fopen (newfile, "r");
- if (newfp == (FILE *)NULL)
- {
- sprintf (errbuf, "%s: can't open newfile %s", cmd, newfile);
- perror (errbuf);
- exit (2);
- }
- }
-
-
- /*
- * close both files
- */
- closefiles ()
- {
- fclose (oldfp);
- fclose (newfp);
- }
-
-
- /*
- * dump contents of symbol table
- * For now, only the old line number and the line of text.
- */
- dumpsym ()
- {
- register int i;
-
- printf ("Symbol Table Contents:\n");
- printf ("------ ----- --------\n");
- printf ("old_line_num: <line of text>\n");
- for (i = 0; i < BIGPRIME; ++i)
- if (symtbl[i].olinenum != 0)
- printf ("%d: %s\n", symtbl[i].olinenum, symtbl[i].stashline);
- }
-
-
- /*
- * get number of old lines which match new lines.
- *
- * return the number of lines number n in the old file such that
- * startline <= n < endline which are linked to lines in the new
- * file, and are strictly monotonically increasing in the new file (doesn't
- * have to be monotonically increasing by one, but it can't be the same).
- * Once the monotonical increase stops, we stop counting.
- * 'startline' is definitely matched to some line in new file.
- */
-
- gomatch (startline, endline)
- int startline,
- endline;
-
- {
- register int count, /* lines counted in old file */
- newi, /* current new line number last matched */
- oldi; /* current old line number */
-
-
- /* stop counting lines if reach endline or find non-monitonical
- * increase in the new file. newi set to zero is virtual line begin.
- */
- for (oldi = startline, count = 0, newi = 0;
- oldi < endline && oldi <= lastold+1; ++oldi)
- if (oa[oldi].flag != L_LINENUM) /* old line doesn't match any new line */
- continue; /* so skip old line */
- else if (oa[oldi].lineloc > newi) /* monotonical? */
- {
- newi = oa[oldi].lineloc; /* yes, save new line number */
- ++count;
- }
- else
- break; /* no, stop counting */
-
- return count;
- }
-
-
- /*
- * same idea as gomatch, except count lines in new file which match lines in
- * old file and old file lines are strictly monotonically increasing
- */
- gnmatch (startline, endline)
- int startline,
- endline;
-
- {
- register int count,
- oldi,
- newi;
-
-
- /* stop counting lines if reach endline or find non-monitonical
- * increase in the old file. oldi set to zero is virtual line begin.
- */
- for (newi = startline, count = 0, oldi = 0;
- newi < endline && newi <= lastnew+1; ++newi)
- if (na[newi].flag != L_LINENUM) /* new line doesn't match any new line */
- continue; /* so skip new line */
- else if (na[newi].lineloc > oldi) /* monotonical? */
- {
- oldi = na[newi].lineloc; /* yes, save old line number */
- ++count; /* bump count */
- }
- else
- break; /* no, stop counting */
-
- return count;
- }
- SHAR_EOF
- if test 34748 -ne "`wc -c < 'hdiff.c'`"
- then
- echo shar: error transmitting "'hdiff.c'" '(should have been 34748 characters)'
- fi
- fi
- echo shar: extracting "'remwhite.c'" '(5649 characters)'
- if test -f 'remwhite.c'
- then
- echo shar: will not over-write existing file "'remwhite.c'"
- else
- cat << \SHAR_EOF > 'remwhite.c'
- /*
- * f=remwhite.c
- * author - dennis bednar 8 30 84
- *
- * library and standalone routine to remove excess white space from a string.
- * If there are multiple white spaces together they are transformed into
- * one blank character. New lines (if any) in the string are not touched.
- * A string can consist of more than one line (ie multiple '\n' newline
- * separators in the string), but usually a string will
- * consist of one line followed by newline, and then terminated.
- *
- * White space at the beginning of each line in the string is reduced to
- * one blank, if rem1stwhite=0;
- * White space at the beginning of each line in the string is reduced to
- * no-blanks, if rem1stwhite=1;
- * White space for between 2nd, 3rd, etc. non-whites is in each line is
- * reduced to one blank.
- * White space at the end of the line in the string is REMOVED.
- */
-
- #include <stdio.h>
- #include "stripnl.h"
-
- char *fgets ();
-
- /* max strlen (number of chars) returned by remwhite */
- #define MAXSTRING 1024
-
- /* max line length that main can handle */
- #define LINESIZE 1024 /* user sees max line length */
- #define _LINESIZE LINESIZE+2 /* declare buffer size room for "\n\0" at end*/
-
-
- /* last char at the end is for the NULL terminator */
- /* this is the output buffer returned by remwhite() */
- static char obuffer [MAXSTRING+1];
-
- char *
- remwhite (inbuf, rem1stwhite)
- char *inbuf;
- char rem1stwhite; /* 0 = leave leading white space if any */
- /* 1 = remove leading white space if any */
-
- {
- register char *src, /* current pointer into input buf */
- *dst, /* current pointer into output buf */
- *end; /* first char AFTER end of output buffer */
- int inwhite; /* true iff in middle of white space */
-
-
- inwhite = 0;
-
- /* initialize the src and dest ptrs */
- src = inbuf;
- dst = obuffer;
-
- nextline:
-
- /* skip over leading white space in this 'line' in input buffer */
- /* DONT treat newlines as white space, otherwise, if there were
- * multiple lines in the input string, then we would remove them,
- * and we don't want to.
- * src is positioned at the beginning of a line within inbuf.
- */
- if (rem1stwhite)
- for (; *src; ++src)
- if (*src == ' ' || *src == '\t')
- continue;
- else
- break; /* found first non-white input char */
-
- /* this logic is implemented to output the blank char AFTER
- * an inwhite to !inwhite state transition.
- * The reason is so that white space at the end
- * of the string will be removed.
- */
- for (end = &obuffer[sizeof(obuffer)]; *src; ++src)
- {
- if (*src == ' ' || *src == '\t')
- inwhite = 1; /* don't output anything, just remember we're seeing white space */
- else if (inwhite) /* transition, time to output the old blank */
- {
- inwhite = 0;
- *dst++ = ' ';
- if (dst >= end)
- goto error;
- *dst++ = *src;
- if (*src == '\n') /* found end of a line in the input buffer */
- goto nextline; /* work on beginning of next line */
- }
- else
- *dst++ = *src;
-
- /* prevent output buffer overflows */
- if (dst >= end)
- {
- error:
- fprintf (stderr, "remwhite: overran buffer. More than %d chars.\n", MAXSTRING);
- exit (5);
- }
- }
-
-
- /* terminate the string */
- *dst = '\0';
-
- return obuffer;
- }
-
- #ifdef STAND
-
- /*
- * test out the remwhite function
- */
-
- static char *cmd; /* name of this command */
-
-
- /*
- * usage:
- cmd [-a] [file ...] # -a means remove leading white space in each line
- # if no file(s) given, use stdin
- */
-
-
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- register int i;
- int striplead = 0; /* default is DONT zap leading blanks */
- /* ie default is to keep leading white space */
- /* 1 would change " 1 2" to "1 2" */
- /* 0 would leave " 1 2" as " 1 2" */
-
- cmd = argv [0];
-
- /* first process possible options */
- for (i = 1; i < argc; ++i)
- if (strcmp(argv[i], "-a") == 0)
- {
- striplead = 1;
- continue;
- }
- else
- break;
-
- /* i now is index of first file in arg list, if any */
-
- if (i == argc)
- dofile ("", striplead); /* read from stdin */
- else for ( ;i < argc; ++i) /* read each file */
- dofile (argv[i], striplead);
-
- exit (0); /* normal */
- }
-
- /*
- * process a file
- */
- dofile (filename, zapflag)
- char *filename;
- int zapflag; /* 1 = zap leading white space */
- {
- FILE *infp, /* input file */
- *fopen (); /* fopen (3) */
-
- if (*filename == '\0')
- {
- filename = "[stdin]"; /* in case we need to print file name */
- infp = stdin;
- }
- else
- {
- infp = fopen (filename, "r");
- if (infp == (FILE *)NULL)
- {
- sprintf (obuffer, "%s: can't open %s", cmd, filename);
- perror (obuffer);
- exit (2);
- }
- }
-
- dolines (infp, filename, zapflag);
-
-
- fclose (infp);
- }
-
-
- /*
- * process the lines
- */
- dolines (infp, filename, zapflag)
- FILE *infp; /* stream pointer to read the input file */
- char *filename; /* name of file we are reading from (for msg) */
- int zapflag; /* 1 = zap leading white space */
- {
- char buffer [_LINESIZE], /* hold line from stdin here */
- *cp; /* get pointer to compressed line */
- int stat, /* status after stripping newline */
- linenum; /* current line number we are reading */
-
- /* read lines from infp and take out the blanks */
- /* print them to show the effect */
- linenum = 0;
- while (fgets (buffer, sizeof(buffer), infp) != (char *) NULL)
- {
- ++linenum;
-
- stat = stripnl (buffer, sizeof(buffer) );
-
- if (stat == L_SUCCESS)
- ; /* okay */
- else if (stat == L_BADFORM)
- fprintf (stderr, "%s: Warning, line %d in file %s not terminated by newline.\n", cmd, linenum, filename);
- else
- {
- fprintf (stderr, "%s: Line %d in file %s longer than %d chars\n", cmd, linenum, filename, LINESIZE);
- exit (4);
- }
-
- cp = remwhite (buffer, zapflag);
-
- printf ("%s\n", cp);
- }
- }
-
-
-
-
- #endif
- SHAR_EOF
- if test 5649 -ne "`wc -c < 'remwhite.c'`"
- then
- echo shar: error transmitting "'remwhite.c'" '(should have been 5649 characters)'
- fi
- fi
- echo shar: extracting "'stripnl.c'" '(1745 characters)'
- if test -f 'stripnl.c'
- then
- echo shar: will not over-write existing file "'stripnl.c'"
- else
- cat << \SHAR_EOF > 'stripnl.c'
- /*
- * f=stripnl.c
- * author - dennis bednar 8 31 84
- *
- * this routine is designed to work in conjunction with fgets ().
- * In this case, the L_BUFOVER error should never be returned, but
- * the check is there anyway!
- *
- * strip new lines by converting the newline in the string to a null
- * returns
- * L_BUFOVER = buffer is overfilled. For example if bufsize = 10, then
- * the string len could be at most 9 (so the NULL fits)
- * L_TOOLONG = no newline was found (line too long) and buffer was filled.
- * For a bufsize of 10, buffer[9] is the last char, and it's
- * not the expected newline.
- * L_BADFORM = no newline was found and buffer not filled, so bad format
- * L_SUCCESS = success
- */
-
- #include "stripnl.h"
-
- stripnl (buffer, bufsize)
- char *buffer;
- int bufsize;
- {
- char *cp;
- int len; /* number of chars in string */
-
-
- /* get string length */
- len = strlen (buffer);
-
- /* make sure it's not already overrun */
- if (len >= bufsize)
- return (L_BUFOVER);
-
- /* if "" is passed, len is zero, and so 'last char' doesn't exist */
- if (len <= 0)
- return (L_BADFORM);
-
- /* now the string definitely fits in the buffer */
-
- /* get pointer to last char in string */
- cp = &buffer [len - 1];
-
- /* if the last char of the string is a newline, change it to a NULL */
- if (*cp == '\n')
- {
- *cp = '\0';
- return L_SUCCESS;
- }
-
- /* now the string fits in the buffer, and the last char != '\n' */
-
- /* line too long if the string length is the buffer size minus
- * one for the null.
- */
- else if (len >= bufsize-1)
- return L_TOOLONG;
-
- /* badly formatted if the line fits in the buffer, but
- * contains no newline at the end.
- * This happens on a file which is corrupted by, say,
- * a transmission error.
- */
- else
- return L_BADFORM;
- }
- SHAR_EOF
- if test 1745 -ne "`wc -c < 'stripnl.c'`"
- then
- echo shar: error transmitting "'stripnl.c'" '(should have been 1745 characters)'
- fi
- fi
- echo shar: extracting "'stripnl.h'" '(125 characters)'
- if test -f 'stripnl.h'
- then
- echo shar: will not over-write existing file "'stripnl.h'"
- else
- cat << \SHAR_EOF > 'stripnl.h'
- /* returned from the function stripnl */
- #define L_BUFOVER -2
- #define L_TOOLONG -1
- #define L_BADFORM 0
- #define L_SUCCESS 1
- SHAR_EOF
- if test 125 -ne "`wc -c < 'stripnl.h'`"
- then
- echo shar: error transmitting "'stripnl.h'" '(should have been 125 characters)'
- fi
- fi
- exit 0
- # End of shell archive
-